home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 25
/
Cream of the Crop 25.iso
/
compress
/
tar321__.zip
/
SOURCES.ZIP
/
LONGDOS.ASM
< prev
next >
Wrap
Assembly Source File
|
1997-03-10
|
16KB
|
856 lines
; This is a replacement for DOS C RTL system functions, which detects
; presence of DOS 7/Chickago Long File Name (LFN) service and use new
; or old interrupt calls respectively to provide uniform interface.
; Directory service is tuned for usage with Portable tar program.
; In particular:
; 1) it always tries FCB-style calls in order to obtain starting cluster
; number (which further used as a part of unique file id),
; 2) thus it is constrained to current directory,
; 3) if cluster number is available then the package tries to resolve
; substituted drives and get "real" drive number,
; 4) the package automatically converts file names to lowercase even
; under DOS 7 until it is really new style name.
include farnear.inc
_DATA segment word public 'DATA'
xfcb_buf db (7+37) dup (0)
search_buf db (44+260+14) dup (0)
longname_buf equ search_buf + 44
oldname_buf equ longname_buf + 260
public _lfn_active
_lfn_active db 255
_DATA ends
routine __IOERROR ; extern int pascal __IOerror()
_TEXT segment byte public 'CODE'
assume cs:_TEXT, ds:NOTHING, es:_DATA
program _dosgetdisk
mov ah,19h
int 21h
cbw
ret
_dosgetdisk endp
program _dossetdisk
push bp
mov bp,sp
mov dl,arglist[0] ; DL = drive
mov ah,0Eh
int 21h
; no error status available - explicitly verify the result
mov ah,19h ; get drive
int 21h
xor al,arglist[0]
jz disk_end
; do not bother to set errno
mov al,-1
disk_end: cbw
pop bp
ret
_dossetdisk endp
seg_DATA dw _DATA
ldata macro rs
mov rs,cs:seg_DATA
endm
check_dos proc near
ldata es
cmp byte ptr es:_lfn_active,0
ret
check_dos endp
check_err proc near
cmp byte ptr es:_lfn_active,0
jg is_error
cmp ah,71h
jne is_error
mov byte ptr es:_lfn_active,0
clc
ret
is_error: stc
ret
check_err endp
set_newdos proc near
mov byte ptr es:_lfn_active,1
ret
set_newdos endp
program _lgetcurdir
; int lgetcurdir(int drive, char far *dest)
push bp
mov bp,sp
push si
push ds
mov dx,arglist[0]
lds si,arglist[2]
call check_dos
je short pwd_old
mov ax,7147h ; get long cwd
stc
int 21h
jc short pwd_check
call set_newdos
jmp short pwd_ok
pwd_check:
call check_err
jc short pwd_error
pwd_old:
mov ah,47h ; get cwd - old style
int 21h
jnc pwd_ok
pwd_error: pop ds
push ax
call __IOERROR
jmp short pwd_end
pwd_ok: xor ax,ax ; AX := 0
pop ds
pwd_end: pop si
pop bp
ret
_lgetcurdir endp
program _laction
; int laction(int a, char far *path)
push bp
mov bp,sp
push ds
mov cx,arglist[0]
lds dx,arglist[2]
do_action:
call check_dos
je short act_old
mov al,cl ; action
mov ah,71h ; long filename call
stc
int 21h
jc short check_act
call set_newdos
jmp short act_ok
check_act:
call check_err
jc short act_error
act_old:
mov ah,cl
int 21h
jnc act_ok
act_error: pop ds
push ax
call __IOERROR
jmp short act_end
act_ok: xor ax,ax ; AX := 0
pop ds
act_end: pop bp
ret
_laction endp
program _lopen4
; int lopen4(char far *filename, int mode, int action, int attributes)
push bp
mov bp,sp
push si
push ds
mode equ arglist[4]
action equ arglist[6]
attribute equ arglist[8]
lds si,arglist[0] ; DS:SI => file name
call check_dos
je short old_open
mov bx,mode
mov dx,action
mov cx,attribute
mov ax,716Ch
stc
int 21h
jc short check_open
call set_newdos
jmp short open_end
check_open:
call check_err
jc short open_error
old_open:
mov dx,si ; DS:DX => file name
mov ax,action
cmp ax,2
je short existance
cmp ax,16
je short existance
cmp ax,18
je short do_create
and al,not 16
dec ax ; 1 or 17
jz short do_open
mov al,1 ; invalid action code
jmp short bad_open
existance:
mov ax,4300h ; get file attributes
int 21h
jc short file_unavailable
; file exists, do we like to truncate it?
test byte ptr action,2
jnz short do_create
mov al,5
jmp short bad_open
do_open:
mov ax,mode
mov ah,3Dh
int 21h
jnc short open_end
file_unavailable:
cmp ax,2 ; check the error code
jne short open_error
; file does not exist, do we like to create it?
test byte ptr action,16
jz short open_error
do_create:
mov cx,attribute
mov ah,3Ch ; create/overwrite
int 21h
jnc short open_end
bad_open:
cbw
open_error:
pop ds ; restore data segment
push ax
call __IOERROR
push ds ; adjustment dummy
open_end: ; return the file handle
pop ds
pop si
pop bp
ret
_lopen4 endp
program _dosclose
; int dosclose(int handle)
push bp
mov bp,sp
mov bx,arglist[0]
pop bp
mov ah,3Eh
int 21h
jc short close_error
xor ax,ax
ret
close_error:
push ax
call __IOERROR
ret
_dosclose endp
program _doswrite
; int doswrite(int handle, void far *buffer, unsigned length)
mov ah,40h
jmp short do_io
_doswrite endp
program _dosread
; int dosread(int handle, void far *buffer, unsigned length)
mov ah,3fh
do_io: push bp
mov bp,sp
push ds
mov bx,arglist[0] ; handle
lds dx,arglist[2] ; buffer
mov cx,arglist[6] ; length
int 21h
jnc short io_end
pop ds ; restore data segment
push ax
call __IOERROR
push ds ; adjustment dummy
io_end: pop ds ; return number of bytes
pop bp
ret
_dosread endp
program _dosseek
; long dosseek(int handle, long offs, int whence)
push bp
mov bp,sp
mov bx,arglist[0] ; handle
mov dx,arglist[2] ; offset, low
mov cx,arglist[4] ; offset, high
mov ax,arglist[6] ; whence
pop bp
mov ah,42h
int 21h
jnc short seek_end
push ax
call __IOERROR
cwd
seek_end: ret
_dosseek endp
program _lchmod
; int lchmod(char far *filename, int op, int mode)
push bp
mov bp,sp
push ds
action equ arglist[4]
lds dx,arglist[0] ; DS:DX => file name
mov bx,action
mov cx,arglist[6] ; CX := mode
call check_dos
je short old_ch
mov ax,7143h
stc
int 21h
jc short check_ch
call set_newdos
jmp short ch_ok
check_ch:
call check_err
jc short ch_error
old_ch:
xchg ax,bx ; BL := action
mov ah,43h
int 21h
jc short ch_error
ch_ok: xor ax,ax
test byte ptr action,1
jz short ch_end
xchg ax,cx
ch_end: pop ds
pop bp
ret
ch_error:
pop ds ; restore data segment
push ax
call __IOERROR
pop bp
ret
_lchmod endp
local_dta proc near
ldata ds
lea dx,_DATA:xfcb_buf
mov ah,1Ah ; set DTA
int 21h
ret
local_dta endp
set_dta macro
mov ah,2fh
int 21h
push es ; preserve DTA
push bx
call local_dta
endm
reset_dta macro
pop dx
pop ds
mov ah,1Ah ; restore DTA
int 21h
endm
old_find1st proc near
; int near pascal old_find1st(void far *fcbP, char far *nameP)
; CL = attributes mask
push bp
mov bp,sp
fcbP equ ss:bp[4]
nameP equ ss:bp[8]
push si
push di
lds si,nameP
les di,fcbP
mov byte ptr es:[di],-1 ; mark an extended FCB
mov es:[di+6],cl
add di,7 ; ES:DI => regular FCB
mov byte ptr es:[di],0
mov ax,2900h
int 21h ; build FCB
pop di
pop si
set_dta
ldata es
lea bx,_DATA:xfcb_buf
mov ah,11h
find_loop:
lds dx,fcbP
int 21h ; perform search
test al,al
jnz short find_done
; ignore LFN records
cmp word ptr es:bx[8+26],0
jne short find_done
cmp byte ptr es:bx[8+11],15
jne short find_done
mov ah,12h
jmp short find_loop
find_done:
xchg ax,bp ; preserve the result
reset_dta
xchg ax,bp ; restore result
test al,al
pop bp
ret 8
old_find1st endp
verify_drive proc near
; convert virtual (substed etc.) drive number to real one
ldata es
lea di,es:xfcb_buf+7
mov dl,es:[di]
mov ah,32h
int 21h
test al,al
jnz drive_done
mov al,ds:[bx]
inc ax
mov es:[di],al
drive_done: ret
verify_drive endp
verify_subst proc near
; same as above, but for LFN-DOS
ldata es
lea di,es:xfcb_buf+7
subst_loop:
mov bl,es:di
mov bh,2
mov ax,71AAh
stc
int 21h
jc short subst_done
mov bx,dx
mov al,ds:bx
and al,not ('z'-'Z')
cmp al,'Z'
ja subst_done
sub al,'A'
jb subst_done
cmp byte ptr ds:[bx+1],':'
jne subst_done
inc ax ; AL := new drive number
cmp al,es:di
je short subst_done
mov es:di,al
jmp short subst_loop
subst_done: ret
verify_subst endp
fill_buf proc near
; CX = Unicode conversion flags
; DS:DI = cwdentP
mov dx,_DATA
lea bx,_DATA:longname_buf
mov ds:di[0],bx
mov ds:di[2],dx
lea bx,_DATA:xfcb_buf+7
mov ds:di[4],bx
mov ds:di[6],dx
assume ds:_DATA
mov ds,dx
; if volume label is set, always fake FCB
xor ax,ax
test byte ptr ds:search_buf,8
jnz short fcb_hook
lea bx,_DATA:oldname_buf
cmp byte ptr ds:[bx],0
je short one_name
test cl,2 ; is shortname realistic?
jnz short fake_fcb
jmp short fill_fcb
; names are the same, use new one
one_name: sub bx,oldname_buf-longname_buf
mov si,bx
lc_loop: lodsb ; convert it to lowercase
cmp al,'A'
jb short lc_next
cmp al,'Z'
ja short lc_next
add al,'z'-'Z'
mov ds:[si-1],al
lc_next: test al,al
jnz short lc_loop
test cl,1
jnz short fake_fcb
; use old-style call to fill FCB
fill_fcb:
push ds
push bx
push ds
lea bx,_DATA:xfcb_buf
push bx
mov cl,ds:search_buf
call old_find1st
jnz short fake_fcb
call verify_subst
ret
fake_fcb:
mov ax,-1
fcb_hook:
ldata ds
lea bx,_DATA:search_buf
lea di,_DATA:xfcb_buf+7
mov ds:di[1+26],ax ; cluster
mov ah,19h
int 21h ; get current drive
inc ax
; do not care to use real drive for fake FCB
mov ds:[di],al ; store it to FCB
mov al,ds:bx
mov ds:di[1+11],al ; attributes
mov ax,ds:bx[20]
mov ds:di[1+22],ax ; time
mov ax,ds:bx[22]
mov ds:di[1+24],ax ; date
mov ax,ds:bx[32]
mov ds:di[1+28],ax ; size, low
mov ax,ds:bx[34]
mov ds:di[1+30],ax ; size, high
ret
assume ds:NOTHING
fill_buf endp
copy_name proc near
mov bx,cx ; preserve count
copy_loop:
lodsb
test al,al
jz short copy_done
test dl,dl
jnz short copy_char
cmp al,'A'
jb short copy_char
cmp al,'Z'
ja short copy_char
add al,'z'-'Z'
copy_char: stosb
loop short copy_loop
copy_done:
neg cx
add cx,bx
jcxz short strip_done
strip_sp: cmp byte ptr es:[di-1],' '
jne short strip_done
dec di
loop short strip_sp
strip_done:
ret
copy_name endp
prepare_name proc near
; DS:SI = cwdentP
mov ax,_DATA
mov es,ax
lea di,_DATA:longname_buf
lea bx,_DATA:xfcb_buf+7
mov ds:si[0],di
mov ds:si[2],es
mov ds:si[4],bx
mov ds:si[6],es
mov ds,ax ; DS := _DATA
mov dl,ds:bx[1+11]
and dl,8 ; isolate label attribute
lea si,[bx+1] ; DS:SI => file name in FCB
mov cx,8
call copy_name
mov bx,si
mov cx,3
check_ext:
lodsb
test al,al
jz short ext_done
cmp al,' '
jne short have_ext
loop check_ext
jmp short ext_done
have_ext:
mov al,'.'
stosb
mov si,bx
mov cx,3
call copy_name
ext_done:
xor al,al
stosb
ret
prepare_name endp
program _lfindfirst
; int lfindfirst(lcwdent_t far *cdwentP, char far *pattern, int attribute)
push bp
mov bp,sp
push si
push di
push ds
cwdentP equ arglist[0]
pattern equ arglist[4]
attribute equ arglist[8]
call check_dos
je short old_search
lds dx,pattern
lea di,es:search_buf ; ES:DI => buf
mov byte ptr es:oldname_buf,0
mov si,1 ; DOS time format
mov cx,attribute
mov ax,714Eh
stc
int 21h
ldata es
lds di,cwdentP
jc short check_search
call set_newdos
mov ds:di[8],ax ; preserve handle
call fill_buf
jmp short search_ok
check_search:
call check_err
jnc short old_search
cmp ax,2 ; file not found?
jne short search_err
; assume it is short name, try old-style search
mov word ptr ds:di[8],-1 ; invalidate handle
lea bx,_DATA:xfcb_buf ; ES:BX => scratch
jmp short old_hook
old_search:
les bx,cwdentP
add bx,8 ; ES:BX => xFCB buffer
old_hook:
push pattern[2]
push pattern[0]
push es
push bx
mov cl,attribute
call old_find1st
jz short use_fcb
mov ax,2
search_err:
pop ds
push ax
call __IOERROR
jmp short search_end
use_fcb:
lds si,cwdentP
call prepare_name
call verify_drive
search_ok:
xor ax,ax
pop ds
search_end:
pop di
pop si
pop bp
ret
_lfindfirst endp
program _lfindnext
push bp
mov bp,sp
push si
push di
push ds
call check_dos
je short old_next
jg short new_next
mov ax,6 ; Hm-m
next_err:
pop ds
push ax
call __IOERROR
jmp short next_end;
new_next:
lds si,arglist[0]
mov bx,ds:si[8] ; search handle
lea di,_DATA:search_buf
mov si,1 ; DOS time format
mov ax,714fh
stc
int 21h
jc next_err
lds di,arglist[0]
call fill_buf
jmp short next_ok
old_next:
set_dta
ldata es
lea bx,_DATA:xfcb_buf
next_loop:
lds dx,arglist[0]
add dx,8 ; DS:DX => FCB from previous search
mov ah,12h ; perform search
int 21h
test al,al
jnz short next_done
; ignore LFN records
cmp word ptr es:bx[8+26],0
jne short next_done
cmp byte ptr es:bx[8+11],15
je short next_loop
next_done:
xchg ax,bx ; preserve the result
reset_dta
test bl,bl
jz short get_name
mov ax,2
jmp short next_err
get_name:
lds si,arglist[0]
call prepare_name
call verify_drive
next_ok:
xor ax,ax
pop ds
next_end:
pop di
pop si
pop bp
ret
_lfindnext endp
program _lfindend
; int lfindend(lcwdent_t far *cdwentP)
call check_dos
je short finish_ok
jg short do_fihish
finish_fail:
mov ax,6 ; Hm-m
finish_err:
push ax
call __IOERROR
ret
do_fihish:
push bp
mov bp,sp
les bx,arglist[0]
pop bp
mov bx,es:bx[4] ; remember the handle
stc
mov ax,71A1h
int 21h
jc short finish_err
finish_ok: xor ax,ax
ret
_lfindend endp
program _lgetmtime
; int lgetmtime(char far *filename)
push bp
mov bp,sp
push ds
call check_dos
je short old_mt
lds dx,arglist[0] ; DS:DX => file name
mov bl,4 ; get last write time
mov ax,7143h
push di
stc
int 21h
mov dx,di
pop di
jc short check_mt
call set_newdos
xchg ax,cx
jmp short mt_ok
check_mt:
call check_err
jnc short old_mt
cmp ax,2 ; assume it was an old name
jne short mt_error
old_mt:
set_dta
lds dx,arglist[0] ; DS:DX => file name
mov cx,3fh ; any attribute
mov ah,4fh
int 21h
jc short mt_fail
reset_dta
ldata ds
les ax,dword ptr ds:xfcb_buf[22]
mov dx,es
mt_ok:
pop ds
pop bp
ret
mt_fail:
xchg ax,bx
reset_dta
xchg ax,bx
mt_error:
pop ds ; restore data segment
push ax
call __IOERROR
cwd
pop bp
ret
_lgetmtime endp
program _lrename
; int lrename(char far *oldname, char far *newname)
push bp
mov bp,sp
push di
push ds
lds dx,arglist[0]
les di,arglist[4]
call check_dos
je short ren_old
mov ax,7156h
stc
int 21h
jc short check_ren
call set_newdos
jmp short ren_ok
check_ren:
call check_err
jc short ren_error
ren_old:
mov ah,56h
int 21h
jnc ren_ok
ren_error: pop ds
push ax
call __IOERROR
jmp short ren_end
ren_ok: xor ax,ax ; AX := 0
pop ds
ren_end: pop di
pop bp
ret
_lrename endp
_TEXT ends
end